/** * (C) Copyright 2013 Jabylon (http://www.jabylon.org) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ /** * (C) Coxcxpyright 2013 Jabylon (http://www.jabylon.org) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jabylon.cdo.server; import java.io.File; import java.util.HashMap; import java.util.Map; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.RegistryFactory; import org.eclipse.emf.cdo.eresource.CDOResource; import org.eclipse.emf.cdo.net4j.CDONet4jSession; import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration; import org.eclipse.emf.cdo.net4j.CDONet4jUtil; import org.eclipse.emf.cdo.server.CDOServerUtil; import org.eclipse.emf.cdo.server.IRepository; import org.eclipse.emf.cdo.server.IStore; import org.eclipse.emf.cdo.server.db.CDODBUtil; import org.eclipse.emf.cdo.server.db.IDBStore; import org.eclipse.emf.cdo.server.db.mapping.IMappingStrategy; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.util.CommitException; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.net4j.acceptor.IAcceptor; import org.eclipse.net4j.db.DBUtil; import org.eclipse.net4j.db.h2.H2Adapter; import org.eclipse.net4j.jvm.IJVMAcceptor; import org.eclipse.net4j.jvm.IJVMConnector; import org.eclipse.net4j.jvm.JVMUtil; import org.eclipse.net4j.util.container.IManagedContainer; import org.eclipse.net4j.util.container.IPluginContainer; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.h2.jdbcx.JdbcDataSource; import org.jabylon.db.migration.DBMigrator; import org.jabylon.properties.PropertiesFactory; import org.jabylon.properties.PropertiesPackage; import org.jabylon.properties.Workspace; import org.jabylon.users.Permission; import org.jabylon.users.Role; import org.jabylon.users.User; import org.jabylon.users.UserManagement; import org.jabylon.users.UsersFactory; import org.jabylon.users.UsersPackage; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.FrameworkUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Activator implements BundleActivator { /** * The shared instance */ private static Activator plugin; /** * The Plugin ID */ public static final String PLUGIN_ID = "org.jabylon.cdo.server"; /** * Returns the shared instance * * @return the shared instance */ public static Activator getDefault() { return plugin; } private IJVMAcceptor acceptor = null; private IRepository repository = null; private static final Logger logger = LoggerFactory.getLogger(Activator.class); /** * The constructor */ public Activator() { } /** * The usual start implementation ... */ @Override public void start(BundleContext context) throws Exception { plugin = this; new Thread(new Runnable() { @Override public void run() { try { //this is quite expensive so we do it in a thread initialize(); } catch (CommitException e) { logger.error("Failed to start CDO",e); } } },"starting database").start(); } protected void initialize() throws CommitException { startRepository(); CDONet4jSession session = createSession(); CDOTransaction transaction = session.openTransaction(); try { initializeWorkspace(transaction); initializeUserManagement(transaction); FrameworkUtil.getBundle(getClass()).getBundleContext().registerService(IAcceptor.class, acceptor, null); } catch (CommitException e) { logger.error("Failed to initialize repository", e); } finally { transaction.close(); session.close(); } } private void initializeUserManagement(CDOTransaction transaction) throws CommitException { CDOResource resource = transaction.getOrCreateResource(ServerConstants.USERS_RESOURCE); if (resource.getContents().isEmpty()) { UserManagement userManagement = UsersFactory.eINSTANCE.createUserManagement(); userManagement.getUsers().add(getAdminUser()); userManagement.getUsers().add(getAnonymousUser()); resource.getContents().add(userManagement); } UserManagement userManagement = (UserManagement) resource.getContents().get(0); addAvailablePermissions(userManagement); Role adminRole = addOrUpdateAdminRole(userManagement); addOrUpdateRegisteredRole(userManagement); addOrUpdateAnonymousRole(userManagement); addAdminUserIfMissing(adminRole, userManagement); addAdditionalPermissions(userManagement); transaction.commit(); } private void addAdditionalPermissions(UserManagement userManagement) { addPermission(userManagement, null, "User:register"); } private Role addOrUpdateRegisteredRole(UserManagement userManagement) { Role role = userManagement.findRoleByName("Registered"); if (role == null) { role = UsersFactory.eINSTANCE.createRole(); role.setName("Registered"); addPermission(userManagement, role, "Workspace:view"); addPermission(userManagement, role, "Project:*:view"); addPermission(userManagement, role, "Project:*:suggest"); userManagement.getRoles().add(role); } return role; } private void addOrUpdateAnonymousRole(UserManagement userManagement) { Role role = userManagement.findRoleByName("Anonymous"); if (role == null) { role = UsersFactory.eINSTANCE.createRole(); role.setName("Anonymous"); addPermission(userManagement, role, "Workspace:view"); addPermission(userManagement, role, "Project:*:view"); userManagement.getRoles().add(role); } User anonUser = userManagement.findUserByName(role.getName()); if (anonUser != null && !anonUser.getRoles().contains(role)) // add anon role if missing anonUser.getRoles().add(role); } private void addPermission(UserManagement userManagement, Role role, String permissionName) { Permission permission = getPermission(userManagement.getPermissions(), permissionName); if(permission==null) { permission = UsersFactory.eINSTANCE.createPermission(); permission.setName(permissionName); userManagement.getPermissions().add(permission); } if(role!=null) role.getPermissions().add(permission); } private Role addOrUpdateAdminRole(UserManagement userManagement) { Role adminRole = userManagement.findRoleByName("Administrator"); if (adminRole == null) adminRole = addAdminRole(userManagement); EList<Permission> allPermissions = userManagement.getPermissions(); Permission wildcardPermission = getPermission(allPermissions, "*"); adminRole.getPermissions().add(wildcardPermission); return adminRole; } private User getAnonymousUser() { User anonymous = UsersFactory.eINSTANCE.createUser(); anonymous.setName("Anonymous"); anonymous.setPassword("ThereIsNoPasswordForAnonymous"); anonymous.setType("DB"); return anonymous; } private User getAdminUser() { User admin = UsersFactory.eINSTANCE.createUser(); admin.setName("Administrator"); admin.setPassword("changeme"); admin.setType("DB"); return admin; } private Role addAdminRole(UserManagement userManagement) { Role adminRole = UsersFactory.eINSTANCE.createRole(); adminRole.setName("Administrator"); userManagement.getRoles().add(adminRole); return adminRole; } private void addAdminUserIfMissing(Role adminRole, UserManagement userManagement) { EList<User> users = userManagement.getUsers(); for (User user : users) { for (Role role : user.getRoles()) { if (role.equals(adminRole)) return; } } User admin = userManagement.findUserByName("Administrator"); admin.getRoles().add(adminRole); } private void addAvailablePermissions(UserManagement userManagement) { IConfigurationElement[] permissions = RegistryFactory.getRegistry().getConfigurationElementsFor("org.jabylon.security.permission"); EList<Permission> dbPermissions = userManagement.getPermissions(); for (IConfigurationElement config : permissions) { String permissionName = config.getAttribute("name"); if (getPermission(dbPermissions, permissionName) != null) continue; String permissionDescription = config.getAttribute("description"); Permission perm = UsersFactory.eINSTANCE.createPermission(); perm.setName(permissionName); perm.setDescription(permissionDescription); dbPermissions.add(perm); } if (getPermission(dbPermissions, "*") == null) { Permission perm = UsersFactory.eINSTANCE.createPermission(); perm.setName("*"); perm.setDescription("All Permissions"); dbPermissions.add(perm); } } private Permission getPermission(EList<Permission> dbPermissions, String permissionName) { for (Permission permission : dbPermissions) { if (permission.getName().equals(permissionName)) return permission; } return null; } private void initializeWorkspace(CDOTransaction transaction) throws CommitException { CDOResource resource = null; if (transaction.hasResource(ServerConstants.WORKSPACE_RESOURCE)) { resource = transaction.getResource(ServerConstants.WORKSPACE_RESOURCE); } else { resource = transaction.createResource(ServerConstants.WORKSPACE_RESOURCE); Workspace workspace = PropertiesFactory.eINSTANCE.createWorkspace(); resource.getContents().add(workspace); } //even if workspace was already present, let's initialize the root again in case we got copied around Workspace workspace = (Workspace) resource.getContents().get(0); URI uri = URI.createFileURI(ServerConstants.WORKSPACE_DIR); logger.debug("Adjust workspace to root: "+uri.toFileString()); File root = new File(ServerConstants.WORKSPACE_DIR); if (!root.exists()) root.mkdirs(); workspace.setRoot(uri); transaction.commit(); } public CDONet4jSession createSession() { IManagedContainer container = IPluginContainer.INSTANCE; IJVMConnector connector = JVMUtil.getConnector(container, "default"); CDONet4jSessionConfiguration config = CDONet4jUtil.createNet4jSessionConfiguration(); config.setConnector(connector); config.setRepositoryName(ServerConstants.REPOSITORY_NAME); CDONet4jSession session = config.openNet4jSession(); // see https://github.com/jutzig/jabylon/issues/148 // disableing the chunking for now in case this is the root cause session.options().setCollectionLoadingPolicy(CDOUtil.createCollectionLoadingPolicy(-1, -1)); session.getPackageRegistry().putEPackage(PropertiesPackage.eINSTANCE); session.getPackageRegistry().putEPackage(UsersPackage.eINSTANCE); return session; } private void startRepository() { IPluginContainer container = IPluginContainer.INSTANCE; logger.info("Starting Repository"); // initialize acceptor if (acceptor == null) { acceptor = JVMUtil.getAcceptor(container, "default"); } if (repository == null) { repository = createRepository(); CDOServerUtil.addRepository(container, repository); logger.info("Repository Started"); } } /** * The usual stop implementation ... BUT including some CDO cleanup. */ @Override public void stop(BundleContext context) throws Exception { plugin = null; if (acceptor != null) LifecycleUtil.deactivate(acceptor); if (repository != null) LifecycleUtil.deactivate(repository); } /** * Create and initialize/configure a repository * * @return the CDO repository created */ private IRepository createRepository() { logger.info("Creating Repository in {}", ServerConstants.WORKING_DIR); Map<String, String> props = new HashMap<String, String>(); // props.put(Props.PROP_SUPPORTING_REVISION_DELTAS, "false"); // props.put(Props.PROP_CURRENT_LRU_CAPACITY, "10000"); // props.put(Props.PROP_REVISED_LRU_CAPACITY, "10000"); return CDOServerUtil.createRepository(ServerConstants.REPOSITORY_NAME, createStore(), props); } private IStore createStore() { final String DATABASE_NAME = ServerConstants.WORKING_DIR + "/cdo/embedded/h2;DB_CLOSE_ON_EXIT=FALSE"; JdbcDataSource dataSource = new JdbcDataSource(); dataSource.setURL("jdbc:h2:" + DATABASE_NAME + ";DB_CLOSE_DELAY=-1"); // myDataSource.setCreateDatabase("create"); // myDataSource.setPort(3306); // myDataSource.setServerName("localhost"); IMappingStrategy mappingStrategy = CDODBUtil.createHorizontalMappingStrategy(false); // IDBStore store = CDODBUtil.createStore(mappingStrategy, // DBUtil.getDBAdapter("derby-embedded"), // DBUtil.createConnectionProvider(myDataSource)); H2Adapter adapter = new H2Adapter(); new DBMigrator().migrate(dataSource); IDBStore store = CDODBUtil.createStore(mappingStrategy, adapter, DBUtil.createConnectionProvider(dataSource)); mappingStrategy.setStore(store); return store; } }